/*!
    \file    main.c
    \brief   TIMER Breath LED demo

    \version 2021-03-23, V2.0.0, demo for GD32F30x
*/

/*
    Copyright (c) 2021, GigaDevice Semiconductor Inc.

    Redistribution and use in source and binary forms, with or without modification, 
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice, this 
       list of conditions and the following disclaimer.
    2. Redistributions in binary form must reproduce the above copyright notice, 
       this list of conditions and the following disclaimer in the documentation 
       and/or other materials provided with the distribution.
    3. Neither the name of the copyright holder nor the names of its contributors 
       may be used to endorse or promote products derived from this software without 
       specific prior written permission.

    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
OF SUCH DAMAGE.
*/

#include <string.h>
#include "gd32f30x.h"
#include "gd32f303e_eval.h"
#include "systick.h"

// 更新事件是不确定的，
// 同一个事件能否产生两次dma请求？，主模式、从模式，然后由从模式产生请求

void gpio_config(void);
void timer_config(void);
void ice_send_dma_config(void);
void ice_send_dma_start(uint32_t num);
void ice_recv_dma_config(void);
void ice_recv_dma_start(uint32_t num);
void ice_recv_dma_config2(void);
void ice_recv_dma_start2(uint32_t num);
void ice_send(uint8_t data0, uint8_t data1);
uint32_t ice_recv(void);
void HAL_GPIO_TogglePin(uint32_t gpio_periph,uint32_t pin);

#define MODEA

#define GPIO_ADDR                 (GPIOA + 0x0C)
#define GPIOA_BSR_ADDR            (GPIOA + 0x10)
#define GPIOA_IDR_ADDR            (GPIOA + 0x08)
#define PERIPH_ALIAS(A, n)        (0x42000000+ (A-0x40000000)*32 +n*4)

#define GPIOB_BSR_ADDR            (GPIOB + 0x10)
// #define PE13_ALIAS              PERIPH_ALIAS(GPIOE->ODR, 13)
// #define PA0_ALIAS               PERIPH_ALIAS(GPIOA->ODR, 0)
// #define PA2_ALIAS               PERIPH_ALIAS(GPIOA->ODR, 2)
#define PA4_ALIAS                  PERIPH_ALIAS(GPIO_ADDR, 4)

#define CH0_CLK_PIN                4
#define CH0_DATA_OUT_PIN           5

#define CH1_CLK_PIN                6
#define CH1_DATA_OUT_PIN           7

#define CH0_DATA_IN_PIN            5
#define CH1_DATA_IN_PIN            7

#define ICE_CLK_HIGH               ((1<<CH0_CLK_PIN)|(1<<CH1_CLK_PIN))
#define ICE_CLK_LOW                (ICE_CLK_HIGH<<16)

// 在 pin 引脚上设置电平为 data
#define ICE_SET_PIN_LEVEL(d)       pin_level_sel[d]


#define ICE_PIN_DATA(pin, data)    ((data) ? (1<<(pin)): (1<<((pin)+16)))

#define ICE_CH0_DATA_OUT0          (ICE_PIN_DATA(CH0_DATA_OUT_PIN, 0) | ICE_CLK_LOW)
#define ICE_CH0_DATA_OUT1          (ICE_PIN_DATA(CH0_DATA_OUT_PIN, 1) | ICE_CLK_LOW)
#define ICE_CH1_DATA_OUT0          (ICE_PIN_DATA(CH1_DATA_OUT_PIN, 0) | ICE_CLK_LOW)
#define ICE_CH1_DATA_OUT1          (ICE_PIN_DATA(CH1_DATA_OUT_PIN, 1) | ICE_CLK_LOW)


#define ICE2_CLK_HIGH               (1<<5)
#define ICE2_CLK_LOW                (ICE2_CLK_HIGH<<16)

uint32_t pin_level_sel[4] = {ICE_CH1_DATA_OUT0|ICE_CH0_DATA_OUT0, ICE_CH1_DATA_OUT0|ICE_CH0_DATA_OUT1,
                             ICE_CH1_DATA_OUT1|ICE_CH0_DATA_OUT0, ICE_CH1_DATA_OUT1|ICE_CH0_DATA_OUT1};

uint32_t portData[16] = {ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,
                         ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH,ICE_CLK_HIGH};


uint32_t portBData[16] = {ICE2_CLK_HIGH,ICE2_CLK_LOW,ICE2_CLK_HIGH,ICE2_CLK_LOW,ICE2_CLK_HIGH,ICE2_CLK_LOW,ICE2_CLK_HIGH,ICE2_CLK_LOW,
                         ICE2_CLK_HIGH,ICE2_CLK_LOW,ICE2_CLK_HIGH,ICE2_CLK_LOW,ICE2_CLK_HIGH,ICE2_CLK_LOW,ICE2_CLK_HIGH,ICE2_CLK_LOW,};

uint16_t portInData[16];

uint32_t debug_buf[32];
uint32_t recv_data;
// uint32_t 
/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
void gpio_config(void)
{
    rcu_periph_clock_enable(RCU_GPIOA);
    rcu_periph_clock_enable(RCU_AF);
    rcu_periph_clock_enable(RCU_GPIOB);
    
    gpio_init(GPIOA, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7);
    gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5);

    /*configure PA8 (TIMER2 CH0) as alternate function*/
    gpio_init(GPIOA,GPIO_MODE_IN_FLOATING,GPIO_OSPEED_50MHZ,GPIO_PIN_8);
}

/*!
    \brief      configure the nested vectored interrupt controller
    \param[in]  none
    \param[out] none
    \retval     none
*/
void nvic_configuration(void)
{
    nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
    nvic_irq_enable(TIMER0_Channel_IRQn, 1, 1);
    nvic_irq_enable(DMA0_Channel1_IRQn, 1, 1);
}

/**
    \brief      configure the TIMER peripheral
    \param[in]  none
    \param[out] none
    \retval     none
  */
void timer_config(void)
{
    /* TIMER0 configuration: generate PWM signals with different duty cycles:
       TIMER0CLK = SystemCoreClock / 120 = 1MHz */
    timer_parameter_struct timer_initpara;
    timer_ic_parameter_struct timer_icinitpara;

    rcu_periph_clock_enable(RCU_TIMER0);
    timer_deinit(TIMER0);

    /* TIMER0 configuration */
    timer_initpara.prescaler         = 0;
    timer_initpara.alignedmode       = TIMER_COUNTER_EDGE;
    timer_initpara.counterdirection  = TIMER_COUNTER_UP;
    timer_initpara.period            = 15-1; // 4MHz
    timer_initpara.period            = 5;
    timer_initpara.clockdivision     = TIMER_CKDIV_DIV1;
    timer_initpara.repetitioncounter = 0;
    timer_init(TIMER0,&timer_initpara);
 
    /* TIMER2 CH0 input capture configuration */
    timer_icinitpara.icpolarity  = TIMER_IC_POLARITY_RISING;
    timer_icinitpara.icselection = TIMER_IC_SELECTION_DIRECTTI;
    timer_icinitpara.icprescaler = TIMER_IC_PSC_DIV1;
    timer_icinitpara.icfilter    = 0x0;
    timer_input_capture_config(TIMER0,TIMER_CH_0,&timer_icinitpara);

    /* clear channel 0 interrupt bit */
    timer_interrupt_flag_clear(TIMER0,TIMER_INT_FLAG_CH0);
    /* channel 0 interrupt enable */
    // timer_interrupt_enable(TIMER0,TIMER_INT_CH0);
    // timer_dma_enable(TIMER0,TIMER_DMA_CH0D);

    /* TIMER0 update DMA request enable */
    // timer_dma_enable(TIMER0,TIMER_DMA_UPD);

    /* auto-reload preload enable */
    //timer_auto_reload_shadow_enable(TIMER0);
    timer_enable(TIMER0);
}

void dma_config(void)
{
    dma_parameter_struct dma_init_struct;

    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA0);

    /* initialize DMA channel4 */
    dma_deinit(DMA0,DMA_CH4);

    /* DMA channel5 initialize */
    // dma_init_struct.periph_addr = (uint32_t)(GPIO_ADDR);
    // dma_init_struct.periph_addr = (uint32_t)(PA4_ALIAS);
    dma_init_struct.periph_addr = (uint32_t)(GPIOA_BSR_ADDR);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.memory_addr = (uint32_t)portData;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_32BIT;
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.number = 16;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0,DMA_CH4,&dma_init_struct);
    
    dma_circulation_disable(DMA0,DMA_CH4);

    /* enable DMA channel4 */
    dma_channel_enable(DMA0,DMA_CH4);
}

/*!
    \brief      main function
    \param[in]  none
    \param[out] none
    \retval     none
*/
int main(void)
{
    
    /* configure the GPIO ports */
    gpio_config();
    
    /* configure the TIMER peripheral */
    timer_config();

    nvic_configuration();

    ice_send_dma_config();
    ice_recv_dma_config();
    
    /* configure systick */
    systick_config();

    for (int i=0; i<4; i++)
    {
        // delay_1ms(10);
        // *(uint32_t *)GPIO_ADDR = 0x10;
        // delay_1ms(10);
        // *(uint32_t *)GPIO_ADDR = 0x00;

        // delay_1ms(10);
        // *(uint32_t *)PA4_ALIAS = 0x1;
        // delay_1ms(10);
        // *(uint32_t *)PA4_ALIAS = 0x00;

        // delay_1ms(10);
        // *(uint32_t *)GPIOB_BSR_ADDR = 0x00000010>>1;
        // delay_1ms(10);
        // *(uint32_t *)GPIOB_BSR_ADDR = 0x00100000>>1;

        // delay_1ms(10);
        // *(uint32_t *)GPIOB_BSR_ADDR = 0x00000010;
        // delay_1ms(10);
        // *(uint32_t *)GPIOB_BSR_ADDR = 0x00100000;

    }
    gpio_bit_reset(GPIOA, GPIO_PIN_4);
    while (1){
        //delay_1ms(10);
        recv_data = 0;
        ice_send(0x5A, 0xCB);
        ice_recv_dma_start(8);
        //dma_config();
        //timer_dma_enable(TIMER0,TIMER_DMA_UPD);
#ifdef MODEA
        ice_send_dma_start(16);
        while(RESET == dma_flag_get(DMA0, DMA_CH4, DMA_INTF_FTFIF)){
        }
        // while(RESET == dma_flag_get(DMA0, DMA_CH1, DMA_INTF_FTFIF)){
        // }
        timer_dma_disable(TIMER0, TIMER_DMA_CH0D);
        timer_dma_disable(TIMER0, TIMER_DMA_UPD);
        recv_data = ice_recv();
        if (recv_data != 0xCB5A)
            __NOP();
        __NOP();
#endif
    }
}


// 一个字节，直接确定序列太麻烦，4bit，16行，然后
#ifdef MODEA

#define ICE_SEND_ONEBIT() \
    do { \
        d0 = (data0 & 0x01); \
        d1 = (data1 & 0x02); \
        portData[i] = ICE_SET_PIN_LEVEL(d0 + d1); \
        data0 >>= 1; \
        data1 >>= 1; \
        i+=2; \
    } while(0)
#endif
// 发送的同时，应该先开启接收，再开启发送
const uint8_t byte_reverse[256] = {
0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF};
// __attribute__((section ("SRAMCODE")))
void ice_send(uint8_t data0, uint8_t data1)
{
    uint32_t d0, d1;
    uint32_t i=1;
    // uint32_t *pData = &portData[i];

    // 发送第一个bit
    data0 = byte_reverse[data0];
    data1 = byte_reverse[data1];
    
    d0 = (data0 & 0x01);
    d1 = (data1 & 0x01)<<1;

    data0 >>= 1;
    
    *(uint32_t *)GPIOA_BSR_ADDR = ICE_SET_PIN_LEVEL(d0 + d1);
    // 希望data0 和 data1 连续存放

#ifdef MODEA
    for (i=1; i<=16; i+=2)
    {
        d0 = (data0 & 0x01);
        d1 = (data1 & 0x02);

        portData[i] = ICE_SET_PIN_LEVEL(d0 + d1);
        data0 >>= 1;
        data1 >>= 1;
    }
    // ICE_SEND_ONEBIT();
    // ICE_SEND_ONEBIT();
    // ICE_SEND_ONEBIT();
    // ICE_SEND_ONEBIT();
    // ICE_SEND_ONEBIT();
    // ICE_SEND_ONEBIT();
    // ICE_SEND_ONEBIT();
    // ICE_SEND_ONEBIT();

#else
    for (int i=0; i<=14; i++)
    {
        *(uint32_t *)GPIOA_BSR_ADDR = ICE_CLK_HIGH;
        i++;
        d0 = (data0 & 0x80)>>7;
        data0 <<= 1;

        d1 = (data1 & 0x80)>>6;
        data1 <<= 1;
        *(uint32_t *)GPIOA_BSR_ADDR = ICE_CLK_LOW | ICE_SET_PIN_LEVEL(d0 + d1);
        __NOP();
        __NOP();
    }
#endif
}

// d0 = data & 0x0F;
// nibble_tbl_sel[d0] // 得到四个值



void ice_send_dma_config(void)
{
    dma_parameter_struct dma_init_struct;

    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA0);

    /* initialize DMA channel5 */
    dma_deinit(DMA0,DMA_CH4);

    /* DMA channel5 initialize */
    // dma_init_struct.periph_addr = (uint32_t)(GPIO_ADDR);
    // dma_init_struct.periph_addr = (uint32_t)(PA4_ALIAS);
    dma_init_struct.periph_addr = (uint32_t)(GPIOA_BSR_ADDR);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.memory_addr = (uint32_t)portData;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_32BIT;
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.number = 0;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0,DMA_CH4,&dma_init_struct);
    
    dma_circulation_disable(DMA0,DMA_CH4);

    /* enable DMA channel5 */
    //dma_channel_enable(DMA0,DMA_CH4);
}


void ice_send_dma_start(uint32_t num)
{
    /* disable DMA a channel */
    DMA_CHCTL(DMA0, DMA_CH4) &= ~DMA_CHXCTL_CHEN;
    /* reset DMA channel registers */
    // DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
    // DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;

    DMA_INTC(DMA0) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, DMA_CH4);

    DMA_CHCNT(DMA0, DMA_CH4) = (num & DMA_CHANNEL_CNT_MASK);
    dma_channel_enable(DMA0,DMA_CH4);
    timer_dma_enable(TIMER0,TIMER_DMA_UPD);
}


void ice_recv_dma_config2(void)
{
    dma_parameter_struct dma_init_struct;
    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA0);

    /* initialize DMA channel_1 */
    dma_deinit(DMA0,DMA_CH1);

    /* DMA channel_1 initialize */
    dma_init_struct.periph_addr = (uint32_t)(GPIOA_IDR_ADDR);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.memory_addr = (uint32_t)portInData;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
    dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
    dma_init_struct.number = 0;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0,DMA_CH1,&dma_init_struct);
    
    dma_circulation_disable(DMA0,DMA_CH1);

    /* enable DMA channel4 */
    //dma_channel_enable(DMA0,DMA_CH1);
}


void ice_recv_dma_config(void)
{
    dma_parameter_struct dma_init_struct;
    /* enable DMA clock */
    rcu_periph_clock_enable(RCU_DMA0);

    /* initialize DMA channel_1 */
    dma_deinit(DMA0,DMA_CH1);

    /* DMA channel_1 initialize */
    dma_init_struct.periph_addr = (uint32_t)(GPIOB_BSR_ADDR);
    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
    dma_init_struct.memory_addr = (uint32_t)portBData;
    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
    dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_32BIT;
    dma_init_struct.memory_width = DMA_MEMORY_WIDTH_32BIT;
    dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
    dma_init_struct.number = 0;
    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
    dma_init(DMA0,DMA_CH1,&dma_init_struct);
    
    dma_circulation_disable(DMA0,DMA_CH1);

    /* enable DMA channel4 */
    //dma_channel_enable(DMA0,DMA_CH1);
}


void ice_recv_dma_start2(uint32_t num)
{
    /* disable DMA a channel */
    DMA_CHCTL(DMA0, DMA_CH1) &= ~DMA_CHXCTL_CHEN;
    /* reset DMA channel registers */
    // DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
    // DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;

    DMA_INTC(DMA0) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, DMA_CH1);

    DMA_CHCNT(DMA0, DMA_CH1) = (num & DMA_CHANNEL_CNT_MASK);

    //dma_interrupt_enable(DMA0, DMA_CH1, DMA_INT_FTF);
    dma_channel_enable(DMA0,DMA_CH1);
    timer_dma_enable(TIMER0,TIMER_DMA_CH0D);
}

void ice_recv_dma_start(uint32_t num)
{
    /* disable DMA a channel */
    DMA_CHCTL(DMA0, DMA_CH1) &= ~DMA_CHXCTL_CHEN;
    /* reset DMA channel registers */
    // DMA_CHCTL(dma_periph, channelx) = DMA_CHCTL_RESET_VALUE;
    // DMA_CHCNT(dma_periph, channelx) = DMA_CHCNT_RESET_VALUE;

    DMA_INTC(DMA0) |= DMA_FLAG_ADD(DMA_CHINTF_RESET_VALUE, DMA_CH1);

    DMA_CHCNT(DMA0, DMA_CH1) = (8 & DMA_CHANNEL_CNT_MASK);

    //dma_interrupt_enable(DMA0, DMA_CH1, DMA_INT_FTF);
    dma_channel_enable(DMA0,DMA_CH1);
    timer_dma_enable(TIMER0,TIMER_DMA_CH0D);
}

#if 0
void ice_send(uint8_t data0, uint8_t data1)
{
    uint32_t d0, d1;
    uint32_t dataSel[4] = {0x5A, 0x4B, 0x3E, 0x25};

    for (int i=1; i<=16; i+=2)
    {
        portData[i] = ICE_CLK_HIGH;
        d0 = (data0 & 0x80)>>7;
        data0 <<= 1;

        d1 = (data1 & 0x80)>>6;
        data1 <<= 1;


        portData[i] = dataSel(d0 + d1);
    }
}
#endif

#define ICE_GET_PIN_DATA(pin)         ((portInData[i] & (1<<pin)) >> pin)
uint32_t ice_recv()
{
    // 数据处理
    uint16_t result = 0;
    for (int i=0; i<8; i++)
    {
        result <<= 1;
        result |= (portInData[i] & (1<<CH0_DATA_IN_PIN)) >> CH0_DATA_IN_PIN;
        result |= ((portInData[i] & (1<<CH1_DATA_IN_PIN)) >> CH1_DATA_IN_PIN) << 8;
    }
    return result;
}

void HAL_GPIO_TogglePin(uint32_t gpio_periph,uint32_t pin)
{
  uint32_t odr;

  /* get current Output Data Register value */
  odr = GPIO_OCTL(gpio_periph);

  /* Set selected pins that were at low level, and reset ones that were high */
  GPIO_BOP(gpio_periph) = ((odr & pin) << 16) | (~odr & pin);
}
